Skip to content

DATAREDIS-1081 - Fix NPE in Reactive Hash commands #516

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed

DATAREDIS-1081 - Fix NPE in Reactive Hash commands #516

wants to merge 1 commit into from

Conversation

zhou-hao
Copy link

in Reactive**Commands, some code is defective. May cause NPE.
e.g.

default Mono<ByteBuffer> hGet(ByteBuffer key, ByteBuffer field) {
		return hMGet(key, Collections.singletonList(field)).map(val -> val.isEmpty() ? null : val.iterator().next());
	}

mytest:

  public static void main(String[] args) {
        Hooks.onOperatorDebug();
        LettuceClientConfiguration clientConfiguration= LettuceClientConfiguration.builder()
            .commandTimeout(Duration.ofMillis(1)) //mock timeout
            .build();

        LettuceConnectionFactory factory = new LettuceConnectionFactory(
            new RedisStandaloneConfiguration("localhost", 6379),
            clientConfiguration);

        factory.afterPropertiesSet();
        operations = new ReactiveRedisTemplate<>(factory, RedisSerializationContext.java());

        getRedisTemplate()
            .opsForHash()
            .get("test","test")
            .as(StepVerifier::create)
            .expectComplete()
            .verify();
    }

@mp911de mp911de changed the title fix issue #DATAREDIS-1081 DATAREDIS-1081 - Fix NPE in Reactive Hash commands Apr 20, 2020
@mp911de
Copy link
Member

mp911de commented Apr 20, 2020

Please provide a test case along with the changes. As per the Redis protocol, the response cannot be empty hence we're not able to reproduce the issue.

@zhou-hao
Copy link
Author

when redis command timeout, the response will be empty.

image

test code:

 Hooks.onOperatorDebug();
   LettuceClientConfiguration clientConfiguration = LettuceClientConfiguration.builder()
                .commandTimeout(Duration.ofMillis(1)) //mock timeout
                .build();

        LettuceConnectionFactory factory = new LettuceConnectionFactory(
                new RedisStandaloneConfiguration("localhost", 6379),
                clientConfiguration);

        factory.afterPropertiesSet();
        ReactiveRedisTemplate<Object, Object> operations = new ReactiveRedisTemplate<>(factory, java());

       operations
                .opsForHash()
                .put("test", "test", "abc")
                .then(operations
                        .opsForHash()
                        .get("test", "test")
                )
                .as(StepVerifier::create)
                .expectNext("abc")
                .verifyComplete();
Suppressed: java.lang.NullPointerException: The mapper returned a null value.
		at java.util.Objects.requireNonNull(Objects.java:228)
		Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Assembly trace from producer [reactor.core.publisher.MonoMapFuseable] :
	reactor.core.publisher.Mono.map(Mono.java:3044)
	org.springframework.data.redis.connection.ReactiveHashCommands.hGet(ReactiveHashCommands.java:289)
Error has been observed at the following site(s):
	|_       Mono.map ⇢ at org.springframework.data.redis.connection.ReactiveHashCommands.hGet(ReactiveHashCommands.java:289)
	|_       Mono.map ⇢ at org.springframework.data.redis.core.DefaultReactiveHashOperations.lambda$get$4(DefaultReactiveHashOperations.java:93)
	|_ Flux.usingWhen ⇢ at org.springframework.data.redis.core.ReactiveRedisTemplate.doInConnection(ReactiveRedisTemplate.java:195)
	|_      Mono.from ⇢ at org.springframework.data.redis.core.ReactiveRedisTemplate.createMono(ReactiveRedisTemplate.java:179)
	|_      Mono.then ⇢ at org.springframework.data.redis.connection.lettuce.LettuceReactiveHashCommandsTests.main(LettuceReactiveHashCommandsTests.java:317)
Stack trace:
			at java.util.Objects.requireNonNull(Objects.java:228)
			at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:107)
			at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1705)
			at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:144)
			at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76)
			at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:73)
			at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onNext(MonoFlatMapMany.java:242)
			at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.innerNext(FluxConcatMap.java:274)

@mp911de
Copy link
Member

mp911de commented Apr 20, 2020

Thanks for the hint. The actual issue is then that errors are not propagated correctly.

@zhou-hao
Copy link
Author

👌

@zhou-hao zhou-hao closed this Apr 20, 2020
@zhou-hao zhou-hao deleted the issue/DATAREDIS-1081 branch May 14, 2020 14:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants